# -*- coding: utf-8 -*- 
# @Time : 2021/10/24 12:22 
# @Author : Dong 
# @File : houses.py
import json
import re

from flask_restful import Resource, marshal_with, marshal, reqparse
from flask import request, jsonify, session, current_app, g

from ihome import constants, redis_store, db
from ihome.models import User, Area, House, Facility, HouseImage
from ihome.utils.image_storage import storage
from ihome.utils import marshal_json
from ihome.utils.commons import data_base_error, login_status
from ihome.utils.response_code import RET, error_map

class Area_infor(Resource):

    @data_base_error
    def get(self):

        resp_json = redis_store.get('area_info')
        if resp_json is not None:
            current_app.logger.debug('hit redis area_info')
            resp_dict = json.loads(resp_json)
            return jsonify(resp_dict)

        area_li = Area.query.all()

        redis_resp = dict(marshal(constants.return_template_json(RET.OK, error_map.get(RET.OK), area_li),marshal_json.data_fields('houses_fields')))
        resp_json = json.dumps(redis_resp,ensure_ascii=False)

        # 将数据存在redis中
        redis_store.setex('area_info',constants.AREA_INFO_REDIS,resp_json)

        resp_dict = json.loads(resp_json)
        return jsonify(resp_dict)

class House_index(Resource):

    def get(self):
        # 从缓存中尝试获取数据
        try:
            ret = redis_store.get("home_page_data")
        except Exception as e:
            current_app.logger.error(e)
            ret = None

        if ret:
            current_app.logger.info("hit house index info redis")
            # 因为redis中保存的是json字符串，所以直接进行字符串拼接返回
            return '{"errno":0, "errmsg":"OK", "data":%s}' % ret, 200, {"Content-Type": "application/json"}
        else:
            try:
                # 查询数据库，返回房屋订单数目最多的5条数据
                houses = House.query.order_by(House.order_count.desc()).limit(constants.HOME_PAGE_MAX_HOUSES)
            except Exception as e:
                current_app.logger.error(e)
                return jsonify(errno=RET.DBERR, errmsg="查询数据失败")

            if not houses:
                return jsonify(errno=RET.NODATA, errmsg="查询无数据")

            redis_resp = dict(marshal(constants.return_template_json(RET.OK, error_map.get(RET.OK), houses),
                                      marshal_json.data_fields('houses_fields')))

            # 将数据转换为json，并保存到redis缓存
            json_houses = json.dumps(redis_resp)  # "[{},{},{}]"
            try:
                redis_store.setex("home_page_data", constants.HOME_PAGE_DATA_REDIS_EXPIRES, json_houses)
            except Exception as e:
                current_app.logger.error(e)

            return '{"errno":0, "errmsg":"OK", "data":%s}' % json_houses, 200, {"Content-Type": "application/json"}


class House_infor_id(Resource):


    def get(self,house_id):
        # 前端在房屋详情页面展示时，如果浏览页面的用户不是该房屋的房东，则展示预定按钮，否则不展示，
        # 所以需要后端返回登录用户的user_id
        # 尝试获取用户登录的信息，若登录，则返回给前端登录用户的user_id，否则返回user_id=-1
        user_id = session.get("user_id", "-1")

        # 校验参数
        if not house_id:
            return jsonify(errno=RET.PARAMERR, errmsg="参数确实")

        # 先从redis缓存中获取信息
        try:
            ret = redis_store.get("house_info_%s" % house_id)
        except Exception as e:
            current_app.logger.error(e)
            ret = None
        if ret:
            current_app.logger.info("hit house info redis")
            return '{"errno":"0", "errmsg":"OK", "data":{"user_id":%s, "house":%s}}' % (user_id, ret), \
                   200, {"Content-Type": "application/json"}

        # 查询数据库
        try:
            house = House.query.get(house_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="查询数据失败")

        if not house:
            return jsonify(errno=RET.NODATA, errmsg="房屋不存在")

        # 将房屋对象数据转换为字典
        try:
            house_data = house.to_full_dict()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DATAERR, errmsg="数据出错")

        # 存入到redis中
        json_house = json.dumps(house_data)
        try:
            redis_store.setex("house_info_%s" % house_id, constants.HOUSE_DETAIL_REDIS_EXPIRE_SECOND, json_house)
        except Exception as e:
            current_app.logger.error(e)

        resp = '{"errno":"0", "errmsg":"OK", "data":{"user_id":%s, "house":%s}}' % (user_id, json_house), \
               200, {"Content-Type": "application/json"}
        return resp


class House_infor(Resource):

    @login_status
    def get(self):
        houses = House.query.filter_by(user_id = g.user.id)
        print(houses)
        redis_resp = dict(marshal(constants.return_template_json(RET.OK, error_map.get(RET.OK), houses),
                                  marshal_json.data_fields('houses_fields')))
        return jsonify(redis_resp)

    @login_status
    # @data_base_error
    def post(self):
        # data = request.json
        args = reqparse.RequestParser() \
            .add_argument('title', type=str, location='json', required=True, help="房屋名不能为空") \
            .add_argument("price", type=str, location='json', required=True, help="房屋单价不能为空") \
            .add_argument("area_id", type=str, location='json', required=True, help="房屋所在城区编号不能为空") \
            .add_argument("address", type=str, location='json', required=True, help="房屋地址不能为空") \
            .add_argument("room_count", type=str, location='json', required=True, help="总房屋数不能为空") \
            .add_argument("acreage", type=str, location='json', required=True, help="房屋面积不能为空") \
            .add_argument("unit", type=str, location='json', required=True, help="房屋布局不能为空") \
            .add_argument("capacity", type=str, location='json', required=True, help="房屋容纳人数不能为空") \
            .add_argument("beds", type=str, location='json', required=True, help="房屋床数不能为空") \
            .add_argument("deposit", type=str, location='json', required=True, help="押金不能为空") \
            .add_argument("min_days", type=str, location='json', required=True, help="最小天数不能为空") \
            .add_argument("max_days", type=str, location='json', required=True, help="最大天数不能为空") \
            .add_argument("facility", type=list, location='json', help="最大天数不能为空") \
            .parse_args()

        try:
            args['price'] = float(args['price'])
            args['deposit'] = float(args['deposit'])
        except Exception as e:
            current_app.logger.debug('price 或者 deposit 转换错误 {}'.format(e))
            return jsonify(constants.return_template_json(RET.PARAMERR, error_map.get(RET.PARAMERR)))

        # 判断城区是否存在
        area = Area.query.get(args['area_id'])

        if area is None:
            return jsonify(constants.return_template_json(RET.NODATA, error_map.get(RET.NODATA)))

        # 保存信息
        house = House(
            user_id = g.user.id,
            area_id = args['area_id'],
            title = args['title'],
            price = args['price'],
            address = args['address'],
            room_count = args['room_count'],
            acreage = args['acreage'],
            unit = args['unit'],
            capacity = args['capacity'],
            beds = args['beds'],
            deposit = args['deposit'],
            min_days = args['min_days'],
            max_days = args['max_days'],
        )

        db.session.add(house)

        # 处理房屋设施的信息
        facilities = args.get('facility')
        facilities = [int(i) for i in facilities]
        if facilities:
            facilities = Facility.query.filter(Facility.id.in_(facilities))

            if facilities:
                house.facilities = facilities

        db.session.add(house)
        db.session.commit()

        return jsonify(constants.return_template_json(RET.OK, error_map.get(RET.OK),{'house_id':house.id}))


class House_image(Resource):

    def get(self):
        pass

    @login_status
    @data_base_error
    def post(self):
        image_file = request.files.get('house_image')
        # data = request.json
        args = reqparse.RequestParser() \
            .add_argument('house_id', type=str, location='form', required=True, help="房屋名不能为空") \
            .parse_args()



        if image_file is None:
            return jsonify(constants.return_template_json(RET.PARAMERR, error_map.get(RET.PARAMERR)))

        house = House.query.get(args['house_id'])

        if house is None:
            return jsonify(constants.return_template_json(RET.NODATA, error_map.get(RET.NODATA)))

        image_data = image_file.read()

        file_name = storage(image_data)

        house_image = HouseImage(
            house_id = house.id,
            url = file_name
        )

        db.session.add(house_image)

        if not house.index_image_url:
            house.index_image_url = file_name
            db.session.add(house)

        db.session.commit()

        image_url = constants.QINIU_URL_DOMAIN + file_name

        return jsonify(constants.return_template_json(RET.OK, error_map.get(RET.OK), {'image_url': image_url}))


class Landlord_house(Resource):

    @login_status
    def get(self):
        """获取房东发布的房源信息条目"""
        try:
            # House.query.filter_by(user_id=user_id)
            user = User.query.get(g.user.id)
            houses = user.houses
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="获取数据失败")

        # 将查询到的房屋信息转换为字典存放到列表中
        houses_list = []
        if houses:
            for house in houses:
                houses_list.append(house.to_basic_dict())
        return jsonify(errno=RET.OK, errmsg="OK", data={"houses": houses_list})





# GET /api/v1.0/houses?sd=2017-12-01&ed=2017-12-31&aid=10&sk=new&p=1
# @api.route("/houses")
# def get_house_list():
#     """获取房屋的列表信息（搜索页面）"""
#     start_date = request.args.get("sd", "")  # 用户想要的起始时间
#     end_date = request.args.get("ed", "")  # 用户想要的结束时间
#     area_id = request.args.get("aid", "")  # 区域编号
#     sort_key = request.args.get("sk", "new")  # 排序关键字
#     page = request.args.get("p")  # 页数
#
#     # 处理时间
#     try:
#         if start_date:
#             start_date = datetime.strptime(start_date, "%Y-%m-%d")
#
#         if end_date:
#             end_date = datetime.strptime(end_date, "%Y-%m-%d")
#
#         if start_date and end_date:
#             assert start_date <= end_date
#     except Exception as e:
#         current_app.logger.error(e)
#         return jsonify(errno=RET.PARAMERR, errmsg="日期参数有误")
#
#     # 判断区域id
#     if area_id:
#         try:
#             area = Area.query.get(area_id)
#         except Exception as e:
#             current_app.logger.error(e)
#             return jsonify(errno=RET.PARAMERR, errmsg="区域参数有误")
#
#     # 处理页数
#     try:
#         page = int(page)
#     except Exception as e:
#         current_app.logger.error(e)
#         page = 1
#
#     # 获取缓存数据
#     redis_key = "house_%s_%s_%s_%s" % (start_date, end_date, area_id, sort_key)
#     try:
#         resp_json = redis_store.hget(redis_key, page)
#     except Exception as e:
#         current_app.logger.error(e)
#     else:
#         if resp_json:
#             return resp_json, 200, {"Content-Type": "application/json"}
#
#     # 过滤条件的参数列表容器
#     filter_params = []
#
#     # 填充过滤参数
#     # 时间条件
#     conflict_orders = None
#
#     try:
#         if start_date and end_date:
#             # 查询冲突的订单
#             conflict_orders = Order.query.filter(Order.begin_date <= end_date, Order.end_date >= start_date).all()
#         elif start_date:
#             conflict_orders = Order.query.filter(Order.end_date >= start_date).all()
#         elif end_date:
#             conflict_orders = Order.query.filter(Order.begin_date <= end_date).all()
#     except Exception as e:
#         current_app.logger.error(e)
#         return jsonify(errno=RET.DBERR, errmsg="数据库异常")
#
#     if conflict_orders:
#         # 从订单中获取冲突的房屋id
#         conflict_house_ids = [order.house_id for order in conflict_orders]
#
#         # 如果冲突的房屋id不为空，向查询参数中添加条件
#         if conflict_house_ids:
#             filter_params.append(House.id.notin_(conflict_house_ids))
#
#     # 区域条件
#     if area_id:
#         filter_params.append(House.area_id == area_id)
#
#     # 查询数据库
#     # 补充排序条件
#     if sort_key == "booking":  # 入住做多
#         house_query = House.query.filter(*filter_params).order_by(House.order_count.desc())
#     elif sort_key == "price-inc":
#         house_query = House.query.filter(*filter_params).order_by(House.price.asc())
#     elif sort_key == "price-des":
#         house_query = House.query.filter(*filter_params).order_by(House.price.desc())
#     else:  # 新旧
#         house_query = House.query.filter(*filter_params).order_by(House.create_time.desc())
#
#     # 处理分页
#     try:
#         #                               当前页数          每页数据量                              自动的错误输出
#         page_obj = house_query.paginate(page=page, per_page=constants.HOUSE_LIST_PAGE_CAPACITY, error_out=False)
#     except Exception as e:
#         current_app.logger.error(e)
#         return jsonify(errno=RET.DBERR, errmsg="数据库异常")
#
#     # 获取页面数据
#     house_li = page_obj.items
#     houses = []
#     for house in house_li:
#         houses.append(house.to_basic_dict())
#
#     # 获取总页数
#     total_page = page_obj.pages
#
#     resp_dict = dict(errno=RET.OK, errmsg="OK", data={"total_page": total_page, "houses": houses, "current_page": page})
#     resp_json = json.dumps(resp_dict)
#
#     if page <= total_page:
#         # 设置缓存数据
#
#         redis_key = "house_%s_%s_%s_%s" % (start_date, end_date, area_id, sort_key)
#         # 哈希类型
#         try:
#             # redis_store.hset(redis_key, page, resp_json)
#             # redis_store.expire(redis_key, constants.HOUES_LIST_PAGE_REDIS_CACHE_EXPIRES)
#
#             # 创建redis管道对象，可以一次执行多个语句
#             pipeline = redis_store.pipeline()
#
#             # 开启多个语句的记录
#             pipeline.multi()
#
#             pipeline.hset(redis_key, page, resp_json)
#             pipeline.expire(redis_key, constants.HOUES_LIST_PAGE_REDIS_CACHE_EXPIRES)
#
#             # 执行语句
#             pipeline.execute()
#         except Exception as e:
#             current_app.logger.error(e)
#
#     return resp_json, 200, {"Content-Type": "application/json"}
#

# redis_store
#
# "house_起始_结束_区域id_排序_页数"
# (errno=RET.OK, errmsg="OK", data={"total_page": total_page, "houses": houses, "current_page": page})
#
#
#
# "house_起始_结束_区域id_排序": hash
# {
#     "1": "{}",
#     "2": "{}",
# }
